package com.quectel.leshan.client;

import org.eclipse.californium.core.CoapClient;
import org.eclipse.californium.core.CoapResource;
import org.eclipse.californium.core.CoapResponse;
import org.eclipse.californium.core.coap.CoAP;
import org.eclipse.californium.core.coap.MediaTypeRegistry;
import org.eclipse.californium.core.coap.Request;
import org.eclipse.californium.core.network.CoapEndpoint;
import org.eclipse.californium.elements.exception.ConnectorException;
import org.eclipse.leshan.client.californium.LeshanClient;
import org.eclipse.leshan.client.californium.LeshanClientBuilder;
import org.eclipse.leshan.client.californium.request.CoapRequestBuilder;
import org.eclipse.leshan.client.object.Device;
import org.eclipse.leshan.client.object.Security;
import org.eclipse.leshan.client.object.Server;
import org.eclipse.leshan.client.resource.ObjectsInitializer;
import org.eclipse.leshan.client.servers.ServerIdentity;
import org.eclipse.leshan.core.LwM2mId;
import org.eclipse.leshan.core.model.InvalidDDFFileException;
import org.eclipse.leshan.core.model.InvalidModelException;
import org.eclipse.leshan.core.model.ObjectLoader;
import org.eclipse.leshan.core.model.StaticModel;
import org.eclipse.leshan.core.node.LwM2mMultipleResource;
import org.eclipse.leshan.core.node.LwM2mObjectInstance;
import org.eclipse.leshan.core.node.LwM2mResource;
import org.eclipse.leshan.core.node.LwM2mResourceInstance;
import org.eclipse.leshan.core.request.BindingMode;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

public class LwM2MClient {

    private static final String[] ddfpaths = new String[] { "LWM2M_Security-v1_0.xml", "LWM2M_Security-v1_1_1.xml",
            "LWM2M_Server-v1_0.xml", "LWM2M_Server-v1_1_1.xml", "LWM2M_Access_Control-v1_0_3.xml",
            "LWM2M_Device-v1_0_3.xml", "LWM2M_Device-v1_1.xml",
            "LWM2M_Connectivity_Monitoring-v1_0_2.xml", "LWM2M_Connectivity_Monitoring-v1_1.xml",
            "LWM2M_Connectivity_Monitoring-v1_2.xml", "LWM2M_Firmware_Update-v1_0_3.xml",
            "LWM2M_Location-v1_0_2.xml", "LWM2M_Connectivity_Statistics-v1_0_4.xml",
            "LWM2M_OSCORE-v1_0_1.xml", "19.xml"};

    public static void main(String[] args) throws InvalidModelException, InvalidDDFFileException, IOException {
        String endpoint = "test_device_123" ; // choose an endpoint name
        LeshanClientBuilder builder = new LeshanClientBuilder(endpoint);

        // create objects
        StaticModel model = new StaticModel(ObjectLoader.loadDdfResources("/models/", ddfpaths));
        ObjectsInitializer initializer = new ObjectsInitializer(model);
        initializer.setInstancesForObject(LwM2mId.SECURITY, Security.noSec("coap://127.0.0.1:5683", 1000));
        initializer.setInstancesForObject(LwM2mId.SERVER, new Server(1000, 5 * 60, BindingMode.U, false));

        //添加设备（需继承自BaseInstanceEnabler）
        TestClientDevice testClientDevice = new TestClientDevice();
        initializer.setInstancesForObject(LwM2mId.DEVICE, testClientDevice);
        DeviceDataEnabler deviceDataEnabler = new DeviceDataEnabler();
        initializer.setInstancesForObject(19, deviceDataEnabler);

        // add it to the client
        builder.setObjects(initializer.createAll());

        LeshanClient client = builder.build();
        client.start();

        //添加Server请求Client的资源，资源名称为：hello_client（Server可以请求客户端的这个资源获取对应的数据）
        client.coap().getServer().add(new HelloCoapResource("hello_client"));

        //创建服务停止时的钩子，销毁客户端（同时会通知服务端设备下线）
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                client.destroy(true); // send de-registration request before destroy
            }
        });


        Timer timer = new Timer("Test");
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                Map<String, ServerIdentity> registeredServers = client.getRegisteredServers();
                System.out.println(registeredServers.toString());
                try {
                    //发起请求（向服务端查询资源）
                    //sendCoapRequest(registeredServers);
                } catch (Exception e) {
                    e.printStackTrace();
                }

                //改变电池电量（可以触发服务端ObservationListener的onResponse）
                //testClientDevice.changeBatteryLevel();

                deviceDataEnabler.changeResource(0);

            }
        }, 10000, 10000);

    }

    private static void sendCoapRequest(Map<String, ServerIdentity> registeredServers) {
        registeredServers.forEach((k, serverIdentity) -> {
            //注意CoapClient的uri地址，ip:port后面带的 ’request_test’ 是服务端CoapResource的名称，比如这里就会找name是的request_test的CoapResource
            CoapClient coapClient = new CoapClient(serverIdentity.getUri() + "/request_test");
            try {
                //发起post请求，payload是请求的内容，CoapResponse是服务端返回的内容
                CoapResponse coapResponse = coapClient.post("abc123", MediaTypeRegistry.TEXT_PLAIN);
                System.out.println(coapResponse.getResponseText());
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }
}
